<?php

namespace App\Http\Middleware;

use Closure;
use GuzzleHttp\Exception\RequestException;
use Log;
use GuzzleHttp\Client;
use Throwable;

class RefreshToken
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string  $guard
     * @return mixed
     */
    public function handle($request, Closure $next, $guard = 'api')
    {
        if (!auth($guard)->check()) {
            $tokens = $this->refreshToken($request->headers->get('RefreshToken'));

            if ($tokens !== false) {
                return $this->setAuthenticationHeader($next, $request, $tokens);
            }
        }

        return $next($request);
    }

    /**
     * 自动更新Token
     * @param $refreshToken
     * @return bool|mixed
     */
    protected function refreshToken($refreshToken)
    {
        Log::debug('自动更新Token-RefreshToken', [$refreshToken]);

        $client = new Client();

        try {
            $url = request()->root() . '/oauth/token';

            $params = [
                'grant_type' => 'refresh_token',
                'client_id' => config('passport.proxy.client_id'),
                'client_secret' => config('passport.proxy.client_secret'),
                'refresh_token' => $refreshToken,
                'scope' => '',
            ];

            $response = $client->request('POST', $url, ['form_params' => $params]);


            if ($response->getStatusCode() !== 401) {
                return json_decode($response->getBody()->getContents(), true);
            }
        } catch (RequestException $exception) {
            return false;
        } catch (Throwable $e) {
            return false;
        }
        
        return false;
    }

    /**
     * Set the authentication header.
     *
     * @param $next
     * @param $request
     * @param $tokens
     * @return mixed
     */
    protected function setAuthenticationHeader($next, $request, $tokens)
    {
        $request->headers->set('Authorization', $tokens['token_type'] . ' ' . $tokens['access_token']);
        $response = $next($request);

        $response->headers->set('TokenType', $tokens['token_type']);
        $response->headers->set('AccessToken', $tokens['access_token']);
        $response->headers->set('RefreshToken', $tokens['refresh_token']);

        return $response;
    }
}
